从用户的角度看文件系统

从用户的角度看, Unix系统中硬盘上的文件组成一颗目录树, 每个目录都包含文件活其他目录

Unix 文件系统内部构造

硬盘实际上是由一些磁性盘片组成的计算机系统的一个设备

第一层抽象: 从磁盘到分区

一个磁盘能够存储大量的数据.就像一个国家能被划分成州或县, 一个磁盘可被划分成分区, 以便在一个大的实体内创建独立的区域. 每个分区都可以看做一个独立的磁盘

第二层抽象: 从磁盘到块序列

一个磁盘由一些磁性盘片组成.每个盘片表面都被划分为很多同心圆, 这些同心圆称作磁道, 每个磁道又进一步被划分成扇区, 每个扇区可以存储一定字节数的数据. 扇区是磁盘上的基本存储单元.

为磁盘编号是一种很重要的方法. 给每个磁盘块分配连续的编号使得系统能够计算磁盘上的每个块. 可以一个磁盘连接一个磁盘地从上倒下给所有块编号, 还可以一个磁道接一个磁道的从外向里给所有块编号. 磁盘上存储数据的软件给磁盘上每条磁道上的每个块分配了一个序号

一个将磁盘扇区编号的系统使得我们可以把磁盘视为一系列的组合.

第三层抽象: 从序列快到三个区域的划分

Unix 使用一个简单的方法将文内内容、文件属性和目录这些不同类型的数据存储在被编号的磁盘上. 它将这些磁盘分成了3部分.

超级块

文件系统中的第一个块被成为超级块. 这个块存放文件系统本身的结构信息, 记录每个区域的大小. 超级块也存放未被使用的磁盘块信息.

i-节点表

文件系统下一个部分被称为 i-节点表. 每个文件都有一些属性, 如大小、文件所有者和最近修改时间等. 这些性质被记录在一个称为 i-节点的结构中.

表中的每个 i-节点都通过位置来标识,例如, 标识为2的i-节点(inode 2) 位于文件系统 i-节点表中的第3个位置

数据区

文件系统的第3个部分是数据区, 文件内容保存在这个区域. 磁盘上所有块的大小都是一样的.如果文件包含了超过一个块的内容, 则文件内容会存放在多个磁盘块中.

文件系统实现: 创建一个文件的过程

文件有内容和属性, 内核将文件内容存放在数据区, 文件属性存放在 i-节点, 文件名存放在目录.

创建一个新文件的4个主要操作如下

1) 存储属性

文件属性的存储: 内核先找到一个空的 i-节点. 内核将文件信息记录其中.

2) 存储数据

文件内容存储: 由于新文件需要 3 个存储磁盘块, 因此内核从自由块列表中找出3个自由块

3) 记录分配情况

文件内容按顺序放在块找到的自由块中. 内核在 inode 的磁盘分布区记录使用的序列块

4) 添加文件名到目录

内核将如后 (inode, filename) 添加到目录文件. 文件名和 i-node 号之间的对应关系 将文件名和文件内容及属性连接了起来

文件下系统的实现: 目录的工作过程

目录是一种包含了文件名字列表的特殊文件, 一个包含了 i-node 号的和文件名的表

理解目录

在文件系统内部, 目录是一个包含文件名与 i-node对的列表的文件.

与目录相关的系统调用

1) mkdir

  mkdir
目标 创建目录
头文件 #include <sys/stat.h> / #include <sys/types.h>
函数原型 int result = mkdir(char *pathname, mode_t mode)
参数 pathname 新建目录/mode 权限位的掩码
返回值 -1 error, 0 成功

2) rmdir

  rmdir
目标 删除一个目录. 此目录必须为空
头文件 #include <unistd.h>
函数原型 int result = rmdir(const char *path);
参数 path 目录名
返回值 -1 error, 0 success

3) unlink

  unlink
目标 删除一个链接
头文件 #include <unistd.h>
函数原型 int result = unlink(const char *path);
参数 path 需删除的链接名
返回值 -1 error, 0 success

unlink 用来删除目录文件中的一个记录, 减少相应i-node 的链接数. 如果该 i-node 的 链接数减位 0, 数据块和 i-node 将被释放. unlink 不能用来删除目录

4) link

  link
目标 创建一个文件的新链接
头文件 #include <unistd.h>
原型 int result = link(const char *orig, const char *new);
参数 orig 原链接的名字 new 新建链接的名字
返回值 -1 error, 0 success

5) rename

  rename
目标 重命名活删除一个链接
头文件 #include <unistd.h>
原型 int result = rename(const char * from, const char *to);
参数 from 原链接名字, to 新链接名字
返回值 -1 error, 0 success

6) chdir

  chdir
目标 改变所嗲用进程的当前目录
头文件 #include <unistd.h>
原型 int result = chdir(const char *path);
参数 path 要到达的目录
返回值 -1 error, 0 success